const path = require('path');
const OSS = require('ali-oss');
const dotenv = require('dotenv');
const readdirp = require('readdirp');
const { createReadStream } = require('fs');

const { config: loadEnvConfig } = dotenv;

// 目录路径
const ROOT_PATH = path.join(__dirname, '../');
const DIST_PATH = path.join(ROOT_PATH, 'dist');

// 加载 env 属性
const ENV_CONFIG_PATH = path.resolve(ROOT_PATH, '.env');
loadEnvConfig({ path: ENV_CONFIG_PATH });

// OSS 参数
const OSS_REGION = process.env.OSS_REGION;
const OSS_ACCESS_KEY_ID = process.env.OSS_ACCESS_KEY_ID;
const OSS_ACCESS_KEY_SECRET = process.env.OSS_ACCESS_KEY_SECRET;
const OSS_BUCKET = process.env.OSS_BUCKET;

// 用户参数和项目参数
const USER_NAME = process.env.USER_NAME;
const PROJ_NAME = process.env.PROJ_NAME;

async function main() {
  if (!OSS_REGION || !OSS_ACCESS_KEY_ID || !OSS_ACCESS_KEY_SECRET || !OSS_BUCKET) {
    console.log(
      'OSS_REGION, OSS_ACCESS_KEY_ID, OSS_ACCESS_KEY_SECRET or OSS_BUCKET is undefined，请在 .env 中进行配置！',
    );
    process.exitCode = 1;
    return;
  }
  if (!USER_NAME) {
    console.log('process.env.USER_NAME 不能为空，请在 .env 中进行配置！');
  }
  if (!PROJ_NAME) {
    console.log('process.env.PROJ_NAME 不能为空，请在 .env 中进行配置！');
  }
  const client = new OSS({
    region: OSS_REGION,
    accessKeyId: OSS_ACCESS_KEY_ID,
    accessKeySecret: OSS_ACCESS_KEY_SECRET,
    bucket: OSS_BUCKET,
  });

  /** 判断文件是否存在 */
  const isExistObject = async objectName => {
    try {
      await client.head(objectName);
      return true;
    } catch (e) {
      return false;
    }
  };

  /** 上传文件 */
  const uploadFile = async (objectName, withHash = false) => {
    const uploadPosition = `${USER_NAME}/${PROJ_NAME}/${objectName}`;
    const file = path.resolve(DIST_PATH, objectName);
    const isExist = withHash ? await isExistObject(uploadPosition) : false;

    if (!isExist) {
      const cacheControl = withHash ? 'max-age: 31536000' : 'no-cache';
      await client.putStream(uploadPosition, createReadStream(file), {
        headers: {
          'Cache-Control': cacheControl,
        },
      });
      console.log(`Upload OSS Done: ${objectName}`);
    } else {
      console.log(`Upload OSS Skip: ${objectName}`);
    }
  };

  const PQueue = await (await import('p-queue')).default;
  const queue = new PQueue({ concurrency: 10 });
  for await (const entry of readdirp(DIST_PATH, { depth: 0, type: 'files' })) {
    queue.add(() => uploadFile(entry.path));
  }
  for await (const entry of readdirp(path.join(DIST_PATH, 'assets'))) {
    queue.add(() => uploadFile(`assets/${entry.path.replaceAll('\\', '/')}`, true));
  }
}

main().catch(e => {
  console.log(e);
  process.exitCode = 1;
});
